package org.zenheart.fxnative.context;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.zenheart.fxnative.utils.FxConst;
import org.zenheart.fxnative.utils.GConst;
import org.zenheart.fxnative.utils.PathUtils;
import org.zenheart.fxnative.utils.ThreadUtils;

import java.io.IOException;
import java.net.URL;
import java.util.concurrent.CountDownLatch;

/**
 * <p>项目名称: generator </p>
 * <p>描述: spring配置类 </p>
 * <p>创建时间: 2021/9/16 </p>
 *
 * @author CKM
 * @version v1.0
 */
@Slf4j
@Component
public class UiContext extends Application implements ApplicationContextAware {

    @Getter
    private static Stage stage;
    private static final CountDownLatch STATE = new CountDownLatch(1);
    private static final FXMLLoader LOADER = new FXMLLoader();
    private static ConfigurableListableBeanFactory BEAN_FACTORY;

    @Override
    public void start(Stage stage) throws Exception {
        stage.getIcons().add(FxConst.LOGO);
        stage.setTitle("javafx开发模板");
        loading(stage);
        ThreadUtils.execute(() -> {
            Parent parent = UiContext.load("Desktop.fxml", stage);
            Platform.runLater(() -> {
                Scene scene = new Scene(parent, GConst.WINDOW_INIT_WIDTH, GConst.WINDOW_INIT_HEIGHT);
                scene.getStylesheets().add(PathUtils.css("global.css"));
                stage.setScene(scene);
                UiContext.gc();
            });
        });
        stage.setResizable(false);
        stage.show();
    }

    private void loading(Stage stage) {
        AnchorPane root = new AnchorPane();
        Image loading = new Image("/assets/icon/loading.gif", true);

        BackgroundSize backgroundSize = new BackgroundSize(BackgroundSize.AUTO, BackgroundSize.AUTO, false, false, true, false);
        BackgroundImage image = new BackgroundImage(loading, BackgroundRepeat.NO_REPEAT, BackgroundRepeat.REPEAT, BackgroundPosition.CENTER, backgroundSize);
        root.setBackground(new Background(image));
        Scene scene = new Scene(root, GConst.WINDOW_INIT_WIDTH, GConst.WINDOW_INIT_HEIGHT);
        stage.setScene(scene);
    }

    public static Parent load(String url, Stage stage) {
        try {
            STATE.await();
            UiContext.stage = stage;
            URL fxml = PathUtils.fxml(url);
            LOADER.setControllerFactory(UiContext::getBean);
            LOADER.setLocation(fxml);
            return LOADER.load();
        } catch (IOException | InterruptedException e) {
            log.error("{}", "加载fxml异常: ", e);
            throw new RuntimeException(e);
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        BEAN_FACTORY = (ConfigurableListableBeanFactory) context.getAutowireCapableBeanFactory();
        STATE.countDown();
    }

    public static <T> T getBean(Class<T> aClass) {
        return BEAN_FACTORY.getBean(aClass);
    }

    public static <T> T getBean(String s, Class<T> aClass) {
        return BEAN_FACTORY.getBean(s, aClass);
    }

    public static void setBean(String beanName, Object obj) {
        BEAN_FACTORY.registerSingleton(beanName, obj);
        BEAN_FACTORY.autowireBean(obj);
    }

    public static void gc() {
        for (int i = 0; i < 2; i++) {
            Thread.yield();
            System.gc();
        }
    }
}
